/*
 * Copyright (c) 2010-2013 Ruben Chakhmakhchyan. All rights reserved.
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Eclipse Public License
 * Version 1.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://opensource.org/licenses/EPL-1.0 and read it before using this file.
 */

#pragma once

// ATL
#include "resource.h"       // main symbols
#include "stdafx.h"
#include "com_i.h"

#include "_IScriptableControlEvents_CP.h"

#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif

#include "async_invoke.h"
#include "plugin_model.h"
#include "plugin.h"


class _Plugin;
class CScriptableImageIndexer;
class CScriptableDeviceIndexer;


// CScriptableControl
class ATL_NO_VTABLE CScriptableControl :
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<CScriptableControl, &CLSID_ScriptableControl>,
	public CComControl<CScriptableControl>,
	public IDispatchImpl<IScriptableControl, &IID_IScriptableControl, &LIBID_comLib>,
	public IProvideClassInfo2Impl<&CLSID_ScriptableControl, NULL, &LIBID_comLib>,
	//public IPersistStreamInitImpl<CIaControl>,
	//public IPersistStorageImpl<CIaControl>,
	public IPersistPropertyBagImpl<CScriptableControl>,
	public IQuickActivateImpl<CScriptableControl>,
	public IObjectSafetyImpl<CScriptableControl, INTERFACESAFE_FOR_UNTRUSTED_CALLER>,
	public IOleControlImpl<CScriptableControl>,
	public IOleObjectImpl<CScriptableControl>,
	public IOleInPlaceActiveObjectImpl<CScriptableControl>,
	public IViewObjectExImpl<CScriptableControl>,
	public IOleInPlaceObjectWindowlessImpl<CScriptableControl>,
	public IDataObjectImpl<CScriptableControl>,
	//public ISupportErrorInfo,
	public ISpecifyPropertyPagesImpl<CScriptableControl>,
	public IConnectionPointContainerImpl<CScriptableControl>,
	public IPropertyNotifySinkCP<CScriptableControl>,
	public CProxy_IScriptableControlEvents<CScriptableControl>
{
	typedef IDispatchImpl<IScriptableControl, &IID_IScriptableControl, &LIBID_comLib> BaseDispatch;

public:

	CScriptableControl();
	~CScriptableControl();

	DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE | OLEMISC_CANTLINKINSIDE | OLEMISC_INSIDEOUT | OLEMISC_ACTIVATEWHENVISIBLE | OLEMISC_SETCLIENTSITEFIRST)

	DECLARE_REGISTRY_RESOURCEID(IDR_SCRIPTABLECONTROL)

	BEGIN_COM_MAP(CScriptableControl)
		COM_INTERFACE_ENTRY(IScriptableControl)
		COM_INTERFACE_ENTRY(IDispatch)
		COM_INTERFACE_ENTRY(IViewObjectEx)
		COM_INTERFACE_ENTRY_IID(IID_IViewObject2, IViewObjectEx)
		COM_INTERFACE_ENTRY_IID(IID_IViewObject, IViewObjectEx)
		COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
		COM_INTERFACE_ENTRY_IID(IID_IOleInPlaceObject, IOleInPlaceObjectWindowless)
		COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleInPlaceObjectWindowless)
		COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
		COM_INTERFACE_ENTRY(IOleControl)
		COM_INTERFACE_ENTRY(IOleObject)
		COM_INTERFACE_ENTRY(IQuickActivate)
		COM_INTERFACE_ENTRY(IObjectSafety)
		COM_INTERFACE_ENTRY(IPersistPropertyBag)
		//COM_INTERFACE_ENTRY(IPersistStorage)
		//COM_INTERFACE_ENTRY(IPersistStreamInit)
		COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
		//COM_INTERFACE_ENTRY(IDataObject)
		COM_INTERFACE_ENTRY(IProvideClassInfo)
		COM_INTERFACE_ENTRY(IProvideClassInfo2)
		COM_INTERFACE_ENTRY(IConnectionPointContainer)
	END_COM_MAP()


	BEGIN_CONNECTION_POINT_MAP(CScriptableControl)
		CONNECTION_POINT_ENTRY(__uuidof(_IScriptableControlEvents))
	END_CONNECTION_POINT_MAP()


	BEGIN_PROP_MAP(CScriptableControl)
		//PROP_DATA_ENTRY("width", m_sizeExtent.cx, VT_UI4)
		//PROP_DATA_ENTRY("height", m_sizeExtent.cy, VT_UI4)
		// Example entries
		// PROP_ENTRY_TYPE("Property Name", dispid, clsid, vtType)
		// PROP_PAGE(CLSID_StockColorPage)
	END_PROP_MAP()


	BEGIN_MSG_MAP(CScriptableControl)

		MESSAGE_HANDLER(WM_CREATE, MessageHandler)
		MESSAGE_HANDLER(WM_ERASEBKGND, MessageHandler)
		MESSAGE_HANDLER(WM_PAINT, OnPaint)
		MESSAGE_HANDLER(WM_SIZE, MessageHandler)
		MESSAGE_HANDLER(WM_LBUTTONDOWN, MessageHandler)
		MESSAGE_HANDLER(WM_LBUTTONUP, MessageHandler)
		MESSAGE_HANDLER(WM_MOUSEMOVE, MessageHandler)
		MESSAGE_HANDLER(WM_KEYUP, MessageHandler)
		MESSAGE_HANDLER(WM_KEYDOWN, MessageHandler)
		MESSAGE_HANDLER(WM_SETFOCUS, MessageHandler)
		MESSAGE_HANDLER(WM_DEVICECHANGE, MessageHandler)

		MESSAGE_HANDLER(WM_CUSTOM_ASYNCCALLBACK, MessageHandler)

		//CHAIN_MSG_MAP(CComControl<CIaControl>)
		//DEFAULT_REFLECTION_HANDLER()
	END_MSG_MAP()

	// Handler prototypes:
	LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	//  LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
	//  LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);

	// IViewObjectEx
	DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)

	// IOleObjectInPlace
	//STDMETHOD(SetObjectRects)(LPCRECT prcPos, LPCRECT prcClip);

	// IPersistPropertyBag
	STDMETHOD(Load)(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog);


	//HRESULT IOleInPlaceObject_UIDeactivate();
	//STDMETHOD(IOleInPlaceObject_SetObjectRects)(LPCRECT prcPos,LPCRECT prcClip);
	// ISupportsErrorInfo
	STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
	// IViewObjectEx
	STDMETHOD(GetViewStatus)(DWORD* pdwStatus);

	// IOleClientSite
	STDMETHOD(SetClientSite)(IOleClientSite *pClientSite);


	// IIaControl
	STDMETHOD(scan)();
	STDMETHOD(rescan)();
	STDMETHOD(upload)(VARIANT* pPages, VARIANT* pFilename, VARIANT* pFormat, VARIANT* pUrl, VARIANT* pUploadId, VARIANT* pResult);
	STDMETHOD(saveToFile)(VARIANT* pPages, VARIANT* pFormat, VARIANT* pPath);
	STDMETHOD(getDevices)();

	STDMETHOD(get_devices)(VARIANT* pVal);

	STDMETHOD(get_pixelType)(VARIANT* pVal);
	STDMETHOD(put_pixelType)(VARIANT* pVal);

	STDMETHOD(get_resolution)(VARIANT* pVal);
	STDMETHOD(put_resolution)(VARIANT* pVal);

	STDMETHOD(get_zoomTool)(VARIANT* pVal);
	STDMETHOD(put_zoomTool)(VARIANT* pVal);

	STDMETHOD(get_zoom)(VARIANT* pVal);
	STDMETHOD(put_zoom)(VARIANT* pVal);

	STDMETHOD(get_panTool)(VARIANT* pVal);
	STDMETHOD(put_panTool)(VARIANT* pVal);

	STDMETHOD(get_cropTool)(VARIANT* pVal);
	STDMETHOD(put_cropTool)(VARIANT* pVal);

	STDMETHOD(get_driverModel)(VARIANT* pVal);
	STDMETHOD(put_driverModel)(VARIANT* pVal);

	STDMETHOD(get_showDeviceUI)(VARIANT* pVal);
	STDMETHOD(put_showDeviceUI)(VARIANT* pVal);

	STDMETHOD(get_selectedImageIndex)(VARIANT* pVal);
	STDMETHOD(put_selectedImageIndex)(VARIANT* pVal);

	STDMETHOD(get_imageQuality)(VARIANT* pVal);
	STDMETHOD(put_imageQuality)(VARIANT* pVal);

	STDMETHOD(get_contrast)(VARIANT* pVal);
	STDMETHOD(put_contrast)(VARIANT* pVal);

	STDMETHOD(get_version)(VARIANT* pVal);

	STDMETHOD(get_autoPosition)(VARIANT* pVal);
	STDMETHOD(put_autoPosition)(VARIANT* pVal);

	STDMETHOD(panX)(VARIANT* pVal);
	STDMETHOD(panY)(VARIANT* pVal);
	STDMETHOD(pan)(VARIANT* pValX, VARIANT* pValY);

	STDMETHOD(rotate)(VARIANT* pVal);

	STDMETHOD(crop)();

	STDMETHOD(selectImage)(VARIANT* pVal);
	STDMETHOD(selectNextImage)();
	STDMETHOD(selectPreviousImage)();

	STDMETHOD(connect)(VARIANT* pResult);
	STDMETHOD(disconnect)();

	STDMETHOD(clear)();

	STDMETHOD(setFilter)(VARIANT* pFormat, VARIANT* pPixelType, VARIANT* pFilter);

	STDMETHOD(getCap)(VARIANT* pCap, VARIANT* pResult );

	STDMETHOD(resume)(VARIANT* pProceed);

	STDMETHOD(get_device)(VARIANT* pVal);
	STDMETHOD(put_device)(VARIANT* pVal);

	STDMETHOD(get_deviceIndex)(VARIANT* pVal);
	STDMETHOD(put_deviceIndex)(VARIANT* pVal);

	STDMETHOD(get_paperSource)(VARIANT* pVal);
	STDMETHOD(put_paperSource)(VARIANT* pVal);

	STDMETHOD(get_autoCompress)(VARIANT* pVal);
	STDMETHOD(put_autoCompress)(VARIANT* pVal);

	STDMETHOD(get_autoCompressionLevel)(VARIANT* pVal);
	STDMETHOD(put_autoCompressionLevel)(VARIANT* pVal);

	STDMETHOD(get_autoCompressInBackground)(VARIANT* pVal);
	STDMETHOD(put_autoCompressInBackground)(VARIANT* pVal);

	STDMETHOD(get_autoPause)(VARIANT* pVal);
	STDMETHOD(put_autoPause)(VARIANT* pVal);

	STDMETHOD(get_isPlatformSupported)(VARIANT* pResult);
	STDMETHOD(get_isFlatbedSupported)(VARIANT* pResult);
	STDMETHOD(get_isFeederSupported)(VARIANT* pResult);
	STDMETHOD(get_isDuplexSupported)(VARIANT* pResult);

	STDMETHOD(get_selectedIndex)(VARIANT* pResult);
	STDMETHOD(get_images)(VARIANT* pResult);

	STDMETHOD(initializeDevice)();
	STDMETHOD(focus)();
	STDMETHOD(deleteImage)(VARIANT* pIndex);
	STDMETHOD(shiftImage)(VARIANT* pIndex);

public:
	virtual HRESULT OnDraw(ATL_DRAWINFO& di);

	DECLARE_PROTECT_FINAL_CONSTRUCT()

	HRESULT FinalConstruct() { return S_OK; }

	void FinalRelease() { }

	//virtual BOOL OnSetObjectRects(LPCRECT lpRectPos, LPCRECT lpRectClip);

	char* getUrl();
	void updateView();
	void setFocus();

public:
	PluginModel* m_model;
	_Plugin* m_plugin;
	IWebBrowser2* m_browser;

private:

	IDispatch* listToArray( List<byte_t>& list );

private:

	CComSafeArray<VARIANT> sa;

	CScriptableImageIndexer* m_imageIndexer;
	CScriptableDeviceIndexer* m_deviceIndexer;
	IDispatch* m_dispImageIndexer;
	IDispatch* m_dispDeviceIndexer;

	char* m_userAgent;
};

OBJECT_ENTRY_AUTO(__uuidof(ScriptableControl), CScriptableControl)
